//
// Copyright (c) 2009 All Right Reserved
//
// vl
//
// 2009-01-01
// Contains ...
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using JetBrains.Annotations;
using LargoCommon.Abstract;
namespace LargoCommon.Music
{
///
/// Harmonic Stream.
///
[UsedImplicitly]
public class HarmonicStream {
#region Fields
///
/// The harmonic bars
///
private List harmonicBars;
#endregion
#region Constructors
///
/// Initializes a new instance of the class.
///
public HarmonicStream() {
this.HarmonicBars = new List();
}
///
/// Initializes a new instance of the class.
///
/// The given header.
public HarmonicStream(MusicalHeader givenHeader)
: this() {
this.Header = givenHeader;
}
///
/// Initializes a new instance of the class.
///
/// The Xml stream.
public HarmonicStream(XElement xstream) //// MusicalHeader header
: this() {
if (xstream == null) {
return;
}
XElement xheader = xstream.Element("Header");
this.Header = new MusicalHeader(xheader);
var xbars = xstream.Elements("Bar");
foreach (var xb in xbars)
{
HarmonicBar harmonicBar = new HarmonicBar(this.Header, xb);
this.HarmonicBars.Add(harmonicBar);
}
//// Determine modality from harmonic structures
foreach (var harmonicBar in this.HarmonicBars) {
var bitArray = new BitArray(this.Header.System.HarmonicOrder);
foreach (var harStruct in harmonicBar.HarmonicStructures) {
if (harStruct == null) {
continue;
}
bitArray = bitArray.Or(harStruct.BitArray);
}
var binStruct = new BinaryStructure(this.Header.System.HarmonicSystem, bitArray);
var harModality = new HarmonicModality(binStruct);
harmonicBar.HarmonicModality = harModality;
}
}
#endregion
#region Properties - Xml
/// Gets Xml representation.
/// Property description.
public virtual XElement GetXElement
{
get
{
XElement xstream = new XElement("Harmony");
xstream.Add(this.Header.GetXElement);
var xheader = this.Header.GetXElement;
xstream.Add(xheader);
//// Structures
foreach (HarmonicBar harBar in this.HarmonicBars) {
//// XElement xstructs = new XElement("Structures");
XElement xbar = new XElement(
"Bar",
new XAttribute("Number", harBar.BarNumber), //// BarNumberInMotive
new XAttribute("OriginalNumber", harBar.OriginalBarNumber),
new XAttribute("Schema", harBar.RhythmicStructure != null ? harBar.RhythmicStructure.ElementSchema : string.Empty));
foreach (HarmonicStructure hstruct in harBar.HarmonicStructures) {
var xstruct = hstruct.GetXElement;
xbar.Add(xstruct); //// xstructs
}
//// xbar.Add(xstructs);
xstream.Add(xbar);
}
return xstream;
}
}
#endregion
#region Public properties
///
/// Gets or sets the harmonic motive bars.
///
///
/// The harmonic motive bars.
///
public IList HarmonicBars
{
get
{
Contract.Ensures(Contract.Result>() != null);
if (this.harmonicBars == null) {
throw new InvalidOperationException("Harmonic bars are null.");
}
return this.harmonicBars;
}
set => this.harmonicBars = (List)value ?? throw new ArgumentException("Argument cannot be empty.", nameof(value));
}
///
/// Gets or sets the header.
///
///
/// The header.
///
public MusicalHeader Header { get; set; }
///
/// Gets the name.
///
///
/// The name.
///
public string Name => this.Header.Name;
///
/// Gets or sets the name of the file.
///
///
/// The name of the file.
///
public string FileName => this.Header.FileName;
///
/// Gets the length.
///
///
/// The length.
///
public int Length => this.HarmonicBars.Count;
#endregion
#region Private properties
#endregion
#region Public static factory methods
///
/// Gets the musical tectonic.
///
/// The given file path.
/// Returns value.
[UsedImplicitly]
public static HarmonicStream GetHarmonicStream(string givenFilePath) {
var fileName = Path.GetFileNameWithoutExtension(givenFilePath);
if (fileName == null) {
return null;
}
//// var setup = MusicalSettings.Singleton;
//// string tectonicFolder = setup.Folders.GetFolder(MusicalFolder.Tectonics);
var root = XmlSupport.GetXDocRoot(givenFilePath);
if (root != null && root.Name == "Harmony") {
var xharmonicStream = root;
var t = new HarmonicStream(xharmonicStream); //// Name = fileName.Trim()
return t;
}
return null;
}
///
/// Extends the harmonic stream.
///
/// The given stream.
/// The given bar count.
/// Returns value.
[UsedImplicitly]
public static HarmonicStream ExtendHarmonicStream(HarmonicStream givenStream, int givenBarCount) {
if (givenStream == null || givenStream.HarmonicBars.Count == givenBarCount) {
return givenStream;
}
var harStream = new HarmonicStream(givenStream.Header);
for (int i = 0; i < givenBarCount; i++) {
var cnt = givenStream.HarmonicBars.Count;
var idx = i % cnt;
var harBar = givenStream.HarmonicBars[idx];
harStream.HarmonicBars.Add(harBar);
}
return harStream;
}
#endregion
#region String representation
/// String representation of the object.
/// Returns value.
public override string ToString() {
var s = new StringBuilder();
s.AppendFormat("HarmonicStream (Length {0})", this.HarmonicBars.Count);
return s.ToString();
}
///
/// Chords to string.
///
/// Returns value.
[UsedImplicitly]
public string ChordsToString() {
var s = new StringBuilder();
foreach (var harBar in this.HarmonicBars) {
s.Append(harBar);
s.AppendLine(" # ");
}
return s.ToString();
}
#endregion
#region Public methods
///
/// Renumbers the bars.
///
[UsedImplicitly]
public void RenumberBars() {
int barNumber = 1;
foreach (var harBar in this.HarmonicBars) {
if (harBar != null)
{
harBar.BarNumber = barNumber++;
}
}
}
///
/// Length Of Motive.
///
/// First Index.
/// Second Index.
/// Returns value.
public int LengthOfMotive(int firstIndex, int secondIndex) {
var shift = 0;
while (secondIndex + shift < this.HarmonicBars.Count) {
var harBar = firstIndex + shift >= 0 ? this.HarmonicBars.ElementAt(firstIndex + shift) : null;
var nextBar = secondIndex + shift >= 0 ? this.HarmonicBars.ElementAt(secondIndex + shift) : null;
if (harBar != null && nextBar != null && string.CompareOrdinal(harBar.UniqueIdentifier, nextBar.UniqueIdentifier) == 0) {
shift++;
}
else {
break;
}
}
return shift;
}
///
/// Equal Segments.
///
/// First Index.
/// Second Index.
/// Minimal Length.
/// Returns value.
public bool EqualSegments(int firstIndex, int secondIndex, int minLength) {
if (firstIndex + minLength > this.HarmonicBars.Count || secondIndex + minLength > this.HarmonicBars.Count) {
return false;
}
var isEqual = true;
for (var shift = 0; shift < minLength; shift++) {
var harBar = firstIndex + shift > 0 ? this.HarmonicBars.ElementAt(firstIndex + shift) : null;
var nextBar = secondIndex + shift > 0 ? this.HarmonicBars.ElementAt(secondIndex + shift) : null;
if (harBar != null && nextBar != null && string.CompareOrdinal(harBar.UniqueIdentifier, nextBar.UniqueIdentifier) == 0) {
continue;
}
isEqual = false;
break;
}
return isEqual;
}
///
/// Write To Motive.
///
/// Harmonic Motive.
/// First Index.
/// Length to write.
public void WriteToMotive(HarmonicMotive harmonicMotive, int firstIndex, int length) { //// int firstBarNumber
var newBarNumber = 1; //// 2016/08 firstBarNumber;
for (var idx = firstIndex; idx < firstIndex + length; idx++) {
if (idx < 0 || idx >= this.HarmonicBars.Count) {
continue;
}
if (harmonicMotive?.HarmonicStream.HarmonicBars == null) {
continue;
}
var harBar = this.HarmonicBars.ElementAt(idx);
if (harBar == null) {
continue;
}
var harmonicBarInMotive = (HarmonicBar)harBar.Clone(); //// 2016/08
harmonicBarInMotive.BarNumber = newBarNumber++; //// 201508
harmonicMotive.AddBar(harmonicBarInMotive);
////core harmonicMotive.Length = harmonicMotive.HarmonicBars.Count();
}
}
#endregion
#region Private static methods
#endregion
#region Private methods
#endregion
}
}